import {dsvFormat} from 'd3-dsv'
import shpConverterText from '../index.js'

// TODO: support other encodings than utf-8
// (Need to update readDelimLines() to work with all encodings)
function readDelimRecords(reader, delim, encoding, filter) {
  const dsv = dsvFormat(delim)
  const records = []
  let retn = readDelimLines(reader, 0, delim, encoding, 1)
  const header = shpConverterText.trimBOM(retn ? retn.text : '')
  let batch = null
  if (!retn) return [] // e.g. empty file
  // read in batches (faster than line-by-line)
  while ((retn = readDelimLines(reader, retn.offset, delim, encoding, 500))) {
    batch = dsv.parse(header + retn.text, filter)
    records.push.apply(records, batch)
  }
  return records
}
function readDelimLines(reader, offs, delim, encoding, lines) {
  const CR = 13
  const LF = 10
  const DQUOTE = 34
  const DELIM = delim.charCodeAt(0)
  let inQuotedField = false
  let buf = reader.readSync(offs)
  let eol = false
  let linesLeft = lines > 0 ? lines : 1
  let c = null
  let prev = null

  for (let i=0, n=buf.length; i<n; i++) {
    c = buf[i]
    if (eol) {
      if (prev == CR && c == LF) {
        // consume LF
      } else {
        eol = false
        linesLeft--
      }
      if (linesLeft <= 0) break
    }
    if (c == DQUOTE) {
      // according to spec, double quotes either enclose a field or are
      // paired inside a quoted field
      // https://tools.ietf.org/html/rfc4180
      // the following handles both cases (no error checking though)
      inQuotedField = !inQuotedField
    } else if (!inQuotedField && (c == CR || c == LF)) {
      eol = true
    }

    if (i == n-1) {
      buf = reader.expandBuffer().readSync(offs)
      n = buf.length
    }
    prev = c
  }
  return i === 0 ? null : {
    offset: i + offs,
    text: shpConverterText.bufferToString(buf, encoding, 0, i)
  }
}

export default {
  readDelimRecords,
}